import java.util.ArrayList;
import java.util.List;

/**
 *给你二叉树的根节点 root ，返回它节点值的 前序 遍历。（使用Morris遍历）
 * https://leetcode.cn/problems/binary-tree-preorder-traversal/
 */
class PreorderTraversalMorris {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        TreeNode prev = null;
        while(root != null){
            if(root.left != null){
                // prev 节点就是当前 root 节点向左走一步，然后一直向右走至无法走为止
                //仍然是先对左子数遍历一下，把root放到最右节点的右指针中去（中左右-->中左右）
                prev = root.left;
                while(prev.right !=null && prev.right != root){
                    prev = prev.right;
                }
                // 让 prev 的右指针指向 root，继续遍历左子树
                //但是因为是前序遍历，所以要先把root的值加入res数组中（中左右-->中左右）
                if(prev.right == null){
                    res.add(root.val);
                    prev.right = root;
                    root = root.left;
                } else{    // 说明左子树已经访问完了，我们需要断开链接
                    prev.right =null;
                    root = root.right;
                }
            } else{  // 如果没有左孩子，则直接访问右孩子 
                       //但是要先把root的值放进res数组中，因为前序是中左右（先读取了“中”的值，再继续遍历右子树）
                res.add(root.val);
                root = root.right;
            }
        }
        return res;
    }
}